home *** CD-ROM | disk | FTP | other *** search
/ NOVA - For the NeXT Workstation / NOVA - For the NeXT Workstation.iso / Apps / ArchiveUtils / nx_arc / arcpack.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-20  |  7.1 KB  |  274 lines

  1. /*
  2.  * $Log:    arcpack.c,v $
  3.  * Revision 1.3  88/04/11  18:57:00  hyc
  4.  * fixed a typo...
  5.  * 
  6.  * Revision 1.2  88/04/11  18:38:15  hyc
  7.  * added support for squashing, re-synch with MTS
  8.  * 
  9.  * Revision 1.1  88/04/11  18:27:10  hyc
  10.  * Initial revision
  11.  * 
  12.  * Revision 1.1  87/12/19  04:05:16  hyc
  13.  * Initial revision
  14.  * 
  15.  * Revision 1.3  87/08/13  17:05:11  hyc
  16.  * Run thru indent, fixed some signed vs. unsigned problems
  17.  * with bp <-> buf, and inbuf and localbuf...
  18.  *  Revision 1.2  87/07/21  08:57:19  hyc *** empty
  19.  * log message ***
  20.  * 
  21.  */
  22.  
  23. /*
  24.  * ARC - Archive utility - ARCPACK
  25.  * 
  26.  * Version 3.46, created on 10/23/86 at 17:47:06
  27.  * 
  28.  * (C) COPYRIGHT 1985,86 by System Enhancement Associates; ALL RIGHTS RESERVED
  29.  * 
  30.  * By:  Thom Henderson
  31.  * 
  32.  * Description: This file contains the routines used to compress a file when
  33.  * placing it in an archive.
  34.  * 
  35.  * Language: Computer Innovations Optimizing C86
  36.  */
  37. #include <stdio.h>
  38. #include "arc.h"
  39. #ifdef MTS
  40. #include <ctype.h>
  41. #endif
  42.  
  43. /* stuff for non-repeat packing */
  44.  
  45. #define DLE 0x90        /* repeat sequence marker */
  46.  
  47. static unsigned char state;    /* current packing state */
  48.  
  49. /* non-repeat packing states */
  50.  
  51. #define NOHIST  0        /* don't consider previous input */
  52. #define SENTCHAR 1        /* lastchar set, no lookahead yet */
  53. #define SENDNEWC 2        /* run over, send new char next */
  54. #define SENDCNT 3        /* newchar set, send count next */
  55.  
  56. /* packing results */
  57.  
  58. static LONG     stdlen;        /* length for standard packing */
  59. static INT      crcval;        /* CRC check value */
  60.  
  61. INT
  62. pack(f, t, hdr)            /* pack file into an archive */
  63.     FILE           *f, *t;    /* source, destination */
  64.     struct heads   *hdr;    /* pointer to header data */
  65. {
  66.     INT             c;    /* one character of stream */
  67.     LONG            ncrlen;    /* length after packing */
  68.     LONG            lzwlen;    /* length after crunching */
  69.     LONG            pred_cm(), sqpred_cm();    /* dynamic crunching cleanup */
  70.     LONG            tloc, ftell();    /* start of output */
  71.     INT             getch();
  72.     INT             getc_ncr();
  73.     INT             putc_pak();
  74.  
  75.     /* first pass - see which method is best */
  76.  
  77.     tloc = ftell(t);    /* note start of output */
  78.  
  79.     if (!nocomp) {        /* if storage kludge not active */
  80.         if (note) {
  81.             printf(" analyzing, ");
  82.             fflush(stdout);
  83.         }
  84.         state = NOHIST;    /* initialize ncr packing */
  85.         stdlen = ncrlen = 0;    /* reset size counters */
  86.         crcval = 0;    /* initialize CRC check value */
  87.         setcode();    /* initialize encryption */
  88.  
  89.         if (dosquash) {
  90.             sqinit_cm(f, t);
  91.             while ((c = getch(f)) != EOF) {    /* for each byte of file */
  92.                 ncrlen++;    /* one more packed byte */
  93.                 sqputc_cm(c, t);    /* see what squashing
  94.                              * can do */
  95.             }
  96.             lzwlen = sqpred_cm(t);
  97.         } else {
  98.             init_cm(f, t);    /* initialize for crunching */
  99.     
  100.             while ((c = getc_ncr(f)) != EOF) {    /* for each byte of file */
  101.                 ncrlen++;    /* one more packed byte */
  102.                 putc_cm(c, t);    /* see what crunching can do */
  103.             }
  104.             lzwlen = pred_cm(t);    /* finish up after crunching */
  105.         }
  106.     } else {        /* else kludge the method */
  107.         stdlen = 0;    /* make standard look best */
  108.         ncrlen = lzwlen = 1;
  109.     }
  110.  
  111.     /* standard set-ups common to all methods */
  112.  
  113.     fseek(f, 0L, 0);    /* rewind input */
  114.     hdr->crc = crcval;    /* note CRC check value */
  115.     hdr->length = stdlen;    /* set actual file length */
  116.     state = NOHIST;        /* reinitialize ncr packing */
  117.     setcode();        /* reinitialize encryption */
  118.  
  119.     /* choose and use the shortest method */
  120.  
  121.     if (kludge && note)
  122.         printf("\n\tS:%ld  P:%ld  C:%ld,\t ", stdlen, ncrlen, lzwlen);
  123.  
  124.     if (stdlen <= ncrlen && stdlen <= lzwlen) {
  125.         if (note) {
  126.             printf("storing, ");    /* store without compression */
  127.             fflush(stdout);
  128.         }
  129.         hdrver = 2;    /* note packing method */
  130.         fseek(t, tloc, 0);    /* reset output for new method */
  131.         if (nocomp) {    /* store only kludge skips things */
  132.             stdlen = crcval = 0;    /* recalc these for kludge */
  133.             while ((c = getch(f)) != EOF)    /* store it straight */
  134.                 putc_pak(c, t);
  135.         } else
  136.             filecopy(f, t, stdlen);    /* else use fast file copier */
  137.         hdr->crc = crcval;
  138.         hdr->length = hdr->size = stdlen;
  139.     } else if (ncrlen < lzwlen) {
  140.         if (note)
  141.             printf("packing, ");    /* pack with repeat
  142.                          * suppression */
  143.         hdrver = 3;    /* note packing method */
  144.         hdr->size = ncrlen;    /* set data length */
  145.         fseek(t, tloc, 0);    /* reset output for new method */
  146.         while ((c = getc_ncr(f)) != EOF)
  147.             putc_pak(c, t);
  148.     } else {
  149.         if (note)
  150.             printf(dosquash ? "squashed, " : "crunched, ");
  151.         hdrver = dosquash ? 9 : 8;
  152.         hdr->size = lzwlen;    /* size should not change */
  153.     }
  154.  
  155.     /* standard cleanups common to all methods */
  156.  
  157.     if (note)
  158.         printf("done.\n");
  159. }
  160.  
  161. /*
  162.  * Non-repeat compression - text is passed through normally, except that a
  163.  * run of more than two is encoded as:
  164.  * 
  165.  * <char> <DLE> <count>
  166.  * 
  167.  * Special case: a count of zero indicates that the DLE is really a DLE, not a
  168.  * repeat marker.
  169.  */
  170.  
  171. INT
  172. getc_ncr(f)            /* get bytes with collapsed runs */
  173.     FILE           *f;    /* file to get from */
  174. {
  175.     static INT      lastc;    /* value returned on last call */
  176.     static INT      repcnt;    /* repetition counter */
  177.     static INT      c;    /* latest value seen */
  178.  
  179.     switch (state) {    /* depends on our state */
  180.     case NOHIST:        /* no relevant history */
  181.         state = SENTCHAR;
  182.         return lastc = getch(f);    /* remember the value next
  183.                          * time */
  184.  
  185.     case SENTCHAR:        /* char was sent. look ahead */
  186.         switch (lastc) {/* action depends on char */
  187.         case DLE:    /* if we sent a real DLE */
  188.             state = NOHIST;    /* then start over again */
  189.             return 0;    /* but note that the DLE was real */
  190.  
  191.         case EOF:    /* EOF is always a special case */
  192.             return EOF;
  193.  
  194.         default:    /* else test for a repeat */
  195.             for (repcnt = 1; (c = getch(f)) == lastc && repcnt < 255; repcnt++);
  196.             /* find end of run */
  197.  
  198.             switch (repcnt) {    /* action depends on run size */
  199.             case 1:/* not a repeat */
  200.                 return lastc = c;    /* but remember value
  201.                              * next time */
  202.  
  203.             case 2:/* a repeat, but too short */
  204.                 state = SENDNEWC;    /* send the second one
  205.                              * next time */
  206.                 return lastc;
  207.  
  208.             default:    /* a run - compress it */
  209.                 state = SENDCNT;    /* send repeat count
  210.                              * next time */
  211.                 return DLE;    /* send repeat marker this
  212.                          * time */
  213.             }
  214.         }
  215.  
  216.     case SENDNEWC:        /* send second char of short run */
  217.         state = SENTCHAR;
  218.         return lastc = c;
  219.  
  220.     case SENDCNT:        /* sent DLE, now send count */
  221.         state = SENDNEWC;
  222.         return repcnt;
  223.  
  224.     default:
  225.         arc_abort("Bug - bad ncr state\n");
  226.     }
  227. }
  228.  
  229. INT
  230. getch(f)            /* special get char for packing */
  231.     FILE           *f;    /* file to get from */
  232. {
  233.     INT             c;    /* a char from the file */
  234. #ifndef MSDOS
  235.     static INT      cr = 0;    /* add \r before \n ? */
  236.  
  237.     if (cr) {
  238.         c = '\n';
  239. #ifdef MTS
  240.         c = toascii(c);
  241. #endif
  242.         crcval = addcrc(crcval, c);
  243.         stdlen++;
  244.         cr = 0;
  245.         return (c);
  246.     }
  247. #endif
  248.  
  249.     if ((c = fgetc(f)) != EOF) {    /* if not the end of file */
  250. #ifndef MSDOS
  251.         if (!image && (c == '\n')) {
  252.             c = '\r';
  253.             cr = 1;
  254.         }
  255. #endif
  256. #ifdef MTS
  257.         if (!image)
  258.             c = toascii(c);
  259. #endif
  260.         crcval = addcrc(crcval, c);    /* then update CRC check
  261.                          * value */
  262.         stdlen++;    /* and bump length counter */
  263.     }
  264.     return c;
  265. }
  266.  
  267. INT
  268. putc_pak(c, f)            /* put a packed byte into archive */
  269.     char            c;    /* byte to put */
  270.     FILE           *f;    /* archive to put it in */
  271. {
  272.     putc_tst(code(c), f);    /* put encoded byte, with checks */
  273. }
  274.